/**
 * @file LogFiles.java
 *
 * Write logs to SD Card.
 *
 * Author: DKE Aerospace Germany GmbH
 *
 * Copyright 2011 European Commission
 *
 * Licensed under the EUPL, Version 1.1 only (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 * http://ec.europa.eu/idabc/eupl
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 *
 **/
package com.dkeaerospace.egnosdemoapp;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;

/**
 * Class to write logs to SD Card.
 **/
public class LogFiles {
  private FileWriter gpxwriter_;
  private BufferedWriter out_;
  private FileWriter internalLogFilewriter_;

  /**
   * LogFiles Constructor 
   * Constructs a file writer to write to a log file.
   * 
   * @param gpxwriter   writer to the File named gpxFile.
   * @param internalLogFilewriter   writer to the File named internalLogFile.
   **/
  public LogFiles(final FileWriter gpxWriter, FileWriter internalLogFilewriter) {
    this.gpxwriter_ = gpxWriter;
    this.internalLogFilewriter_ = internalLogFilewriter;
  }

  /**
   * logToSDCard1 function 
   * Start a thread to write to SD Card for values from
   * BluetoothConnectionThread.java.
   * 
   * @param m28      Message 28.
   * @param m41      Message 41.
   * @param coordinates    Latitude and longitude obtained from 
   *                       GPS-Software-Receiver.
   **/
  public final void logToSDCard1(final StringBuffer m28,
      final StringBuffer m41, final double[] coordinates) {
    BackgroundThreadWrite1 writeThread = new BackgroundThreadWrite1(m28, m41,
        coordinates);
    writeThread.start();
  }

  /**
   * BackgroundThreadWrite1 thread 
   * Background thread that writes to the log file.
   **/
  class BackgroundThreadWrite1 extends Thread {
    StringBuffer m28_;
    StringBuffer m41_;
    StringBuffer m28sorted_;
    double[] coordinates_;

    /**
     * BackgroundThreadWrite1 function 
     * Start a thread to write to SD Card for values from Receivermessages.java.
     * 
     * @param m28    Filtered message28 based on sync flags.
     * @param m41    Message 41.
     * @param coordinates   The position coordinates.
     **/
    BackgroundThreadWrite1(StringBuffer m28, StringBuffer m41,
        double[] coordinates) {
      this.coordinates_ = coordinates;
      this.m28_ = m28;
      this.m41_ = m41;
    }

    @Override
    public void run() {
      writeToSDCard1(m28_, m41_, coordinates_);
    };
  }

  /**
   * writeToSDCard1 function 
   * Write log file to Android mobile device SD Card named gpxfile.gpx.
   * 
   * @param m28    Message 28.
   * @param m41    Message 41.
   * @param coordinates   Latitude and longitude obtained from 
   *                      GPS-Software-Receiver.
   **/
  public final void writeToSDCard1(StringBuffer m28, StringBuffer m41,
      double[] coordinates) {
    try {
      out_ = new BufferedWriter(gpxwriter_);
      Date dt = new Date();
      String curTime = dt.toString();
      out_.write("\n" + curTime + "\n");
      out_.write(m28.toString() + "\n");
      if (coordinates != null) {
        out_.write("GPS Latitude:" + coordinates[0] + "\n");
        out_.write("GPS Longitude:" + coordinates[1] + "\n");
        out_.write("GPS Altitude:" + coordinates[2] + "\n");
        out_.write("EGNOS Latitude:" + coordinates[3] + "\n");
        out_.write("EGNOS Longitude:" + coordinates[4] + "\n");
        out_.write("EGNOS Altitude:" + coordinates[5] + "\n");
      } else {
        out_.write("Latitude:" + null + "\n");
        out_.write("Longitude:" + null + "\n");
        out_.write("Altitude:" + null + "\n");
        out_.write("EGNOS Latitude:" + null + "\n");
        out_.write("EGNOS Longitude:" + null + "\n");
        out_.write("EGNOS Altitude:" + null + "\n");
      }
      out_.write(m41.toString() + "\n");
      out_.flush();
    } catch (IOException e) {
      System.out.println("Error: occured in writing to SD Card" + e);
    }
  }

  /**
   * logToSDCard2 function 
   * Start a thread to write to SD Card for values from
   * Receivermessages.java.
   * 
   * @param allMessages     Valid messages from the bluetooth receiver
   *                        as hexadecimal strings starting with a0a2 
   *                        and ending with b0b3.
   * @param m28             Filtered message28 based on sync flags.
   * @param m41             Message 41.
   * @param m28sorted       Sorted message28 in the ascending order.
   * @param recMsg          All messages from the bluetooth receiver 
   *                        as hexadecimal strings.
   **/
  public final void logToSDCard2(final StringBuffer allMessages,
      final StringBuffer m28, final StringBuffer m41,
      final StringBuffer m28sorted, final String recMsg) {
    BackgroundThreadWrite2 writeThread = new BackgroundThreadWrite2(
        allMessages, m28, m41, m28sorted, recMsg);
    writeThread.start();
  }

  /**
   * BackgroundThreadWrite2 thread 
   * Background thread that writes to the log file.
   **/
  class BackgroundThreadWrite2 extends Thread {
    private StringBuffer allMessages_;
    private StringBuffer m28_;
    private StringBuffer m41_;
    private StringBuffer m28sorted_;
    private String recMsg_;

    /**
     * BackgroundThreadWrite2 constructor
     * 
     * @param allMessages   Valid messages from the bluetooth receiver as
     *                      hexadecimal strings starting with a0a2 and
     *                      ending with b0b3.
     * @param m28           Filtered message28 based on sync flags.
     * @param m41           Message 41.
     * @param m28sorted     Sorted message28 in the ascending order.
     * @param recMsg        All messages from the bluetooth receiver 
     *                      as hexadecimal strings.
     **/
    BackgroundThreadWrite2(StringBuffer allMessages, StringBuffer m28,
        StringBuffer m41, StringBuffer m28sorted, String recMsg) {
      this.allMessages_ = allMessages;
      this.m28_ = m28;
      this.m41_ = m41;
      this.m28sorted_ = m28sorted;
      this.recMsg_ = recMsg;
    }

    @Override
    public void run() {
      writeToSDCard2(allMessages_, m28_, m41_, m28sorted_, recMsg_);
    };
  }

  /**
   * writeToSdCard2 function 
   * Another function that creates a log file, this time for EGNOS data.
   * 
   * @param m28         Filtered message28 based on sync flags.
   * @param m41         Message 41.
   * @param m28sorted   Sorted message28 in the ascending order.
   * @param recMsg      All messages from the bluetooth receiver 
   *                    as hexadecimal strings.
   **/
  public final void writeToSDCard2(StringBuffer messages, StringBuffer m28,
      StringBuffer m41, StringBuffer m28sorted, String recMsg) {
    try {
      out_ = new BufferedWriter(gpxwriter_);
      Date dt = new Date();
      String curTime = dt.toString();
      out_.write("\n" + curTime + "\n");
      out_.write(recMsg + "\n");
      out_.write(messages.toString() + "\n");
      out_.write(m28.toString() + "\n");
      out_.write(m41.toString() + "\n");
      out_.write(m28sorted.toString() + "\n");
      out_.flush();
    } catch (IOException e) {
      System.out.println("Error: occured in writing to SD Card (" + e + ").");
    }
  }

  /**
   * logEgnosToSdCard function 
   * Log the EGNOS data to the logfile stored on the SD-card.
   * 
   * @param mT         The message type.
   * @param message    The EGNOS message, 250bits, binary representation.
   **/
  public final void logEgnosToSdCard(final String mT, final String message) {
    BackgroundThreadWriteEgnos writeThread = new BackgroundThreadWriteEgnos(mT,
        message);
    writeThread.start();
  }

  /**
   * BackgroundThreadWriteEgnos thread
   * Background thread that writes to the log file.
   **/
  class BackgroundThreadWriteEgnos extends Thread {
    private String sfrbMT_;
    private String sfrbMessage_;

    /**
     * BackgroundThreadWriteEgnos constructor 
     * Write log file to android mobile device SD Card named gpxfile.gpx.
     * 
     * @param mT         The message type.
     * @param message    The EGNOS message, 250bits, binary representation.
     **/
    BackgroundThreadWriteEgnos(final String mT, final String message) {
      this.sfrbMT_ = mT;
      this.sfrbMessage_ = message;
    }

    @Override
    public void run() {
      writeSfrbToSdCard(sfrbMT_, sfrbMessage_);
    };
  }

  /**
   * writeSfrbToSdCard function
   * Write log file to android mobile device SD Card named gpxfile.gpx.
   * 
   * @param mT         The message type.
   * @param message    The EGNOS message, 250bits, binary representation.
   **/
  public final void writeSfrbToSdCard(String mT, String message) {
    try {
      out_ = new BufferedWriter(gpxwriter_);
      Date dt = new Date();
      String curTime = dt.toString();
      out_.write("\n" + curTime + "\n");
      out_.write(mT + "\n");
      out_.write(message + "\n");
      out_.flush();
    } catch (IOException e) {
      System.out.println("Error: occured in writing to SD Card" + e);
    }
  }

  /**
   * lograwToSdCard function 
   * Log the GPS raw data to the logfile stored on the SD-card.
   * 
   * @param rxmRaw    The raw GPS data from the receiver.
   **/
  public final void logUBloxPositionToSdCard(final double[] position,
      int egnos, int sisnet, int network) {
    BackgroundThreadWriteUBloxPosition writeThread = new BackgroundThreadWriteUBloxPosition(
        position, egnos, sisnet, network);
    writeThread.start();
  }

  /**
   * BackgroundThreadWriteEgnos thread 
   * Background thread that writes to the log file.
   **/
  class BackgroundThreadWriteUBloxPosition extends Thread {
    private double[] currentPosition_;
    private int egnos_;
    private int sisnet_;
    private int network_;

    /**
     * BackgroundThreadWriteUBloxPosition constructor 
     * Write log file to android mobile devices' SD Card named gpxfile.gpx.
     * 
     * @param currentPosition_    The raw GPS data from the receiver.
     * @param sisnet_             0 or 1 if sisnet is used to get EGNOS position.
     * @param egnos_              0 or 1 if egnos data is available.
     * @param network_            0 or 1 if device is connected to the Internet.
     **/
    BackgroundThreadWriteUBloxPosition(final double[] position, int egnos,
        int sisnet, int network) {
      this.currentPosition_ = position;
      this.egnos_ = egnos;
      this.sisnet_ = sisnet;
      this.network_ = network;
    }

    @Override
    public void run() {
      writeUBloxPositionToSdCard(currentPosition_, egnos_, sisnet_, network_);
    };
  }

  /**
   * writeRawToSdCard function 
   * Write log file to android mobile devices' SD Card named gpxfile.gpx.
   * 
   * @param currentPosition_    The raw GPS data from the receiver.
   * @param sisnet_             0 or 1 if sisnet is used to get EGNOS position.
   * @param egnos_              0 or 1 if egnos data is available.
   * @param network_            0 or 1 if device is connected to the Internet.
   **/
  public final void writeUBloxPositionToSdCard(double[] currentPosition_,
      int egnos_, int sisnet_, int network_) {
    String egnosString = "";
    String sisnetString = "";
    String networkString = "";
    try {
      out_ = new BufferedWriter(gpxwriter_);
      Date dt = new Date();
      String curTime = dt.toString();
      out_.write("\n" + curTime + "\n");
      if (egnos_ != 0)
        egnosString = "ON";
      else
        egnosString = "OFF";
      if (sisnet_ != 0)
        sisnetString = "ON";
      else
        sisnetString = "OFF";

      if (network_ != 0)
        networkString = "ON";
      else
        networkString = "OFF";

      out_.write("\nuBlox Egnos : " + egnosString + "\n");
      out_.write("uBlox SISNeT : " + sisnetString + "\n");
      out_.write("Internet : " + networkString + "\n");
      if (currentPosition_ != null) {
        out_.write("GPS Latitude: " + currentPosition_[0] + "\n");
        out_.write("GPS Longitude: " + currentPosition_[1] + "\n");
        out_.write("GPS Altitude:" + currentPosition_[2] + "\n");
        out_.write("EGNOS Latitude: " + currentPosition_[3] + "\n");
        out_.write("EGNOS Longitude: " + currentPosition_[4] + "\n");
        out_.write("EGNOS Altitude: " + currentPosition_[5] + "\n");
      } else {
        out_.write("GPS Latitude: " + null + "\n");
        out_.write("GPS Longitude: " + null + "\n");
        out_.write("GPS Altitude: " + null + "\n");
        out_.write("EGNOS Latitude: " + null + "\n");
        out_.write("EGNOS Longitude: " + null + "\n");
        out_.write("EGNOS Altitude: " + null + "\n\n");
      }
      out_.flush();

      out_ = new BufferedWriter(internalLogFilewriter_);
      if (currentPosition_ != null) {
        out_.write(currentPosition_[0] + "," + currentPosition_[1] + ","
            + currentPosition_[2] + "," + currentPosition_[3] + ","
            + currentPosition_[4] + "," + currentPosition_[5] + ","
            + currentPosition_[7] + "," + currentPosition_[8] + ","
            + currentPosition_[9] + "," + currentPosition_[6] + "\n");
      } else {
        out_.write(null + "\n");
      }
      out_.flush();
    } catch (IOException e) {
      System.out.println("Error: occured in writing to SD Card" + e);
    }
  }

  /**
   * lograwToSdCard function 
   * Log the GPS raw data to the logfile stored on the SD-card.
   * 
   * @param rxmRaw       The raw GPS data from the receiver.
   **/
  public final void logRawToSdCard(final String rxmRaw) {
    BackgroundThreadWriteRaw writeThread = new BackgroundThreadWriteRaw(rxmRaw);
    writeThread.start();
  }

  /**
   * BackgroundThreadWriteEgnos thread 
   * Background thread that writes to the log file.
   **/
  class BackgroundThreadWriteRaw extends Thread {
    private String rxmRaw_;

    /**
     * BackgroundThreadWriteRaw constructor 
     * Write log file to android mobile devices' SD Card named gpxfile.gpx.
     * 
     * @param rxmRaw     The raw GPS data from the receiver.
     **/
    BackgroundThreadWriteRaw(final String rxmRaw) {
      this.rxmRaw_ = rxmRaw;
    }

    @Override
    public void run() {
      writeRawToSdCard(rxmRaw_);
    };
  }

  /**
   * writeRawToSdCard function
   * Write log file to android mobile devices' SD Card named gpxfile.gpx.
   * 
   * @param rxmRaw       The raw GPS data from the receiver.
   **/
  public final void writeRawToSdCard(String rxmRaw) {
    try {
      out_ = new BufferedWriter(gpxwriter_);
      // Date dt = new Date();
      // String curTime = dt.toString();
      // out.write("\n" + curTime + "\n");
      out_.write(rxmRaw + "\n");
      out_.flush();
    } catch (IOException e) {
      System.out.println("Error: occured in writing to SD Card" + e);
    }
  }
}
